﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.Diagnostics;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using log4net.Core;
using System.Threading;
using System.Collections;
using System.IO;
using System.Windows.Forms;
using Wintellect.PowerCollections;
using System.Globalization;

namespace NHTrace
{
  public class DebugController
  {
    public DebugController(DTE2 applicationObject, 
      NHTracePackage package, 
      RemotingReceiverProvider receiverProvider,
      LoggerProvider loggerProvider,
      DebugProcessTracker processTracker,
      int logCharSize)
    {
      _logCharSize = logCharSize;
      _processTracker = processTracker;
      _loggerProvider = loggerProvider;
      _receiverProvider = receiverProvider;
      _package = package;
      _applicationObject = applicationObject;
    }

    public void Initialize()
    {
      _applicationObject.Events.DebuggerEvents.OnEnterRunMode += DebuggerEvents_OnEnterRunMode;
      _applicationObject.Events.DebuggerEvents.OnEnterDesignMode += DebuggerEvents_OnEnterDesignMode;
    }

    private DTE2 _applicationObject;
    private NHTracePackage _package;
    private RemotingReceiver _receiver;
    private Logger _logger;
    private RemotingReceiverProvider _receiverProvider;
    private LoggerProvider _loggerProvider;
    private DebugProcessTracker _processTracker;
    private int _logCharSize;

    private static bool reasonIsStopDebugger(dbgEventReason Reason)
    {
      return (Reason == dbgEventReason.dbgEventReasonEndProgram) ||
        (Reason == dbgEventReason.dbgEventReasonStopDebugging) ||
        (Reason == dbgEventReason.dbgEventReasonDetachProgram);
    }

    private static bool reasonIsStartDebugger(dbgEventReason Reason)
    {
      return (Reason == dbgEventReason.dbgEventReasonGo) ||
        (Reason == dbgEventReason.dbgEventReasonAttachProgram);
    }

    private void DebuggerEvents_OnEnterRunMode(dbgEventReason Reason)
    {
      if (reasonIsStartDebugger(Reason))
      {
        _processTracker.UpdateProcessesBeingDebugged(_applicationObject.Debugger.DebuggedProcesses);

        if (_receiver == null)
        {
          _logger = _loggerProvider.GetLogger(_processTracker, _package, _logCharSize);
          _receiver = _receiverProvider.GetReceiver(_logger);
          _receiver.Initialize();
          _logger.Initialize();
        }
      }
    }

    private void DebuggerEvents_OnEnterDesignMode(dbgEventReason Reason)
    {
      if (reasonIsStopDebugger(Reason))
      {
        _processTracker.UpdateProcessesBeingDebugged(_applicationObject.Debugger.DebuggedProcesses);
        if ((_receiver != null) && (!_processTracker.AreProcessesBeingDebugged))
        {
          try
          {
            _logger.Terminate();
            _receiver.Terminate();
          }
          finally
          {
            _receiver = null;
          }
        }
      }
    }
  }
}
